﻿using System;
using System.Collections.Generic;
using System.Linq;
using DeepZoomPivotConstructor.PivotLib;
using HtmlAgilityPack;
using System.IO;
using DeepZoomPivotConstructor.VisualLib;
using RenderEngineInterfaces;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using PaperPluginUtilities;

namespace ATLASConfNotes
{
    /// <summary>
    /// Helper class to scan over the cells a table and keep information
    /// from cell-to-cell. This can not be done in parallel!!!
    /// </summary>
    [Export]
    public class CellInfoConverter
    {
        /// <summary>
        /// The render engine that can do our actual work.
        /// </summary>
        [Import(typeof(IRenderEngine))]
        private IRenderEngine MyRenderer;

        /// <summary>
        /// Iterator that returns the images found in each cell... basically,
        /// each time a link is found.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public IEnumerable<PivotImage> ProcessCell(HtmlNode node)
        {
            ///
            /// Get all the text nodes out of this first.
            /// 

            var textNodes = from t in node.ScanSubNodes(n => n.NodeType == HtmlNodeType.Text)
                            let txt = t.InnerText
                            where !String.IsNullOrWhiteSpace(txt)
                            select t.InnerText;

            string descr = String.Join(" ", textNodes);
            if (descr.Length > 0)
            {
                Description = descr.CleanHTMLText();
            }

            ///
            /// Now look for some links, and turn each one into an image, along with rendering
            /// the things we want to see!
            ///

            if (!(Description.Contains("Main document")))
            {
                var htmlLinks = from t in node.ScanSubNodes("a")
                                from link in new EnumerableWrapper<HtmlAttribute>(t.Attributes)
                                where link.Name == "href"
                                select link.Value;

                var htmlLinksByName = from t in htmlLinks
                                      let name = Path.GetFileNameWithoutExtension(t)
                                      group t by name;

                foreach (var item in htmlLinksByName)
                {
                    var allUrls = from u in item
                                  select new Uri(BaseUri, u);

                    /// Get out the sipmlest url...

                    var url = GetBestUrl(allUrls, new string[] { ".png", ".jpg", ".jpeg", ".eps", ".ps" });

                    /// Render it to a visual we can deal with.

                    Visual v = MyRenderer.Render(url, forceAsComposableUnit: true);
                    if (v != null)
                    {
                        PivotImage img = new PivotImage(v);
                        img.Name = Path.GetFileNameWithoutExtension(item.First()).CleanHTMLText();
                        img.Description = Description;
                        img.Add("Caption", Description);
                        allUrls.Apply(u => img.Add("Graphics Files", GetUrlExtensions(u).Substring(1), u)).Last();
                        yield return img;
                    }
                }
            }
        }

        /// <summary>
        /// Given a URI, see if we can figure out what the connected file's type is
        /// without actually loading the thing.
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private string GetUrlExtensions(Uri url)
        {
            return Path.GetExtension(url.Segments.Last());
        }

        /// <summary>
        /// Look through the given urls and find the first one that matchs, or
        /// the first one.
        /// </summary>
        /// <param name="allUrls"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        private Uri GetBestUrl(IEnumerable<Uri> allUrls, string[] bestExtensions)
        {
            foreach (var ext in bestExtensions)
            {
                var foundUrls = allUrls.FirstOrDefault(u => GetUrlExtensions(u) == ext);
                if (foundUrls != null)
                {
                    return foundUrls;
                }
            }
            return allUrls.FirstOrDefault();
        }

        private string Description { get; set; }

        /// <summary>
        /// Get/Set the base URI used to deal with relative URL's that come in.
        /// </summary>
        public Uri BaseUri { get; set; }
    }
}
